#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
FastAPI 黄金投资分析后端服务
提供黄金价格获取和AI投资分析API
支持每日缓存机制和跨域请求
"""

import os
import json
import logging
from datetime import datetime, date
from typing import Dict, Any, Optional
from fastapi import FastAPI, HTTPException, status
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from pydantic import BaseModel
import uvicorn

from utils import OpenAIClient
from gold_price_fetcher import get_cngold_realtime_price

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

# 创建FastAPI应用
app = FastAPI(
    title="黄金投资分析API",
    description="提供实时黄金价格和AI投资分析服务",
    version="1.0.0",
    docs_url="/docs",
    redoc_url="/redoc"
)

# 配置CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # 在生产环境中应该设置具体的域名
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 配置文件路径
CONFIG_FILE = "config.json"
# 缓存文件路径
CACHE_FILE = "analysis_cache.json"

# 全局变量
openai_client = None
app_config = None

class AnalysisRequest(BaseModel):
    """分析请求模型"""
    model: Optional[str] = "moonshot-v1-8k"
    temperature: Optional[float] = 0.7
    force_refresh: Optional[bool] = False

class GoldPriceResponse(BaseModel):
    """金价响应模型"""
    price: float
    time: str
    source: str
    timestamp: str

class AnalysisResponse(BaseModel):
    """分析响应模型"""
    analysis: str
    gold_price: float
    price_time: str
    data_source: str
    timestamp: str
    model_used: str
    cached: bool
    usage: Optional[Dict] = None

def load_app_config() -> Dict[str, Any]:
    """加载应用配置"""
    global app_config
    try:
        if os.path.exists(CONFIG_FILE):
            with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
                app_config = json.load(f)
                logger.info(f"成功加载配置文件: {CONFIG_FILE}")
                
                # 验证必要的配置项
                if not app_config.get('openai_api_key'):
                    logger.warning("配置文件中缺少 openai_api_key")
                
                # 显示配置的后端信息
                base_url = app_config.get('openai_base_url', 'https://api.openai.com/v1')
                logger.info(f"配置的大模型后端: {base_url}")
                
                return app_config
        else:
            logger.error(f"配置文件不存在: {CONFIG_FILE}")
            logger.error("请参考 config.example.json 创建配置文件")
            return {}
    except Exception as e:
        logger.error(f"加载配置文件失败: {e}")
        return {}

def init_openai_client():
    """初始化OpenAI客户端"""
    global openai_client
    try:
        # 首先加载配置
        config = load_app_config()
        if not config:
            logger.error("无法加载配置文件，OpenAI客户端初始化失败")
            return False
        
        # 使用配置初始化客户端
        openai_client = OpenAIClient(config_file=CONFIG_FILE)
        if not openai_client.client:
            logger.error("OpenAI客户端初始化失败")
            return False
        
        # 显示初始化成功的信息
        base_url = config.get('openai_base_url', 'https://api.openai.com/v1')
        logger.info("OpenAI客户端初始化成功")
        logger.info(f"使用的API后端: {base_url}")
        
        return True
    except Exception as e:
        logger.error(f"初始化OpenAI客户端时出错: {e}")
        return False

def load_cache() -> Dict[str, Any]:
    """加载缓存数据"""
    try:
        if os.path.exists(CACHE_FILE):
            with open(CACHE_FILE, 'r', encoding='utf-8') as f:
                return json.load(f)
    except Exception as e:
        logger.error(f"加载缓存失败: {e}")
    return {}

def save_cache(data: Dict[str, Any]):
    """保存缓存数据"""
    try:
        with open(CACHE_FILE, 'w', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
        logger.info("缓存数据已保存")
    except Exception as e:
        logger.error(f"保存缓存失败: {e}")

def is_same_day(timestamp1: str, timestamp2: str) -> bool:
    """检查两个时间戳是否在同一天"""
    try:
        date1 = datetime.fromisoformat(timestamp1).date()
        date2 = datetime.fromisoformat(timestamp2).date()
        return date1 == date2
    except:
        return False

def get_cached_analysis(today: str) -> Optional[Dict[str, Any]]:
    """获取缓存的分析结果"""
    cache = load_cache()
    if 'last_analysis' in cache:
        last_analysis = cache['last_analysis']
        if is_same_day(last_analysis.get('timestamp', ''), today):
            logger.info("使用缓存的分析结果")
            return last_analysis
    return None

@app.on_event("startup")
async def startup_event():
    """应用启动时的初始化"""
    logger.info("启动黄金投资分析API服务...")
    if not init_openai_client():
        logger.warning("OpenAI客户端初始化失败，部分功能可能不可用")
    logger.info("API服务启动完成")

@app.get("/", summary="服务状态检查")
async def root():
    """根路径，返回服务状态"""
    global app_config
    if not app_config:
        app_config = load_app_config()
    
    backend_info = "未知"
    if app_config and app_config.get('openai_base_url'):
        base_url = app_config['openai_base_url']
        if 'moonshot' in base_url:
            backend_info = "月之暗面 (Moonshot AI)"
        elif 'openai.com' in base_url:
            backend_info = "OpenAI 官方"
        elif 'api2d' in base_url:
            backend_info = "API2D"
        elif 'openai-sb' in base_url:
            backend_info = "OpenAI-SB"
        else:
            backend_info = f"自定义后端 ({base_url})"
    
    return {
        "message": "黄金投资分析API服务",
        "version": "1.0.0",
        "status": "running",
        "backend": backend_info,
        "timestamp": datetime.now().isoformat(),
        "endpoints": {
            "gold_price": "/api/gold/price",
            "analysis": "/api/gold/analysis",
            "reset_cache": "/api/admin/reset",
            "config_info": "/api/config/info",
            "cache_status": "/api/admin/cache/status",
            "health": "/health",
            "docs": "/docs"
        }
    }

@app.get("/api/gold/price", response_model=GoldPriceResponse, summary="获取实时金价")
async def get_gold_price():
    """获取实时黄金价格"""
    try:
        logger.info("获取实时金价...")
        price, time_str, source = get_cngold_realtime_price()
        
        if price <= 0:
            raise HTTPException(
                status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
                detail="无法获取金价数据"
            )
        
        response = GoldPriceResponse(
            price=price,
            time=time_str,
            source=source,
            timestamp=datetime.now().isoformat()
        )
        
        logger.info(f"金价获取成功: {price} 元/克")
        return response
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取金价时出错: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取金价失败: {str(e)}"
        )

@app.post("/api/gold/analysis", response_model=AnalysisResponse, summary="获取黄金投资分析")
async def get_gold_analysis(request: AnalysisRequest):
    """获取AI黄金投资分析"""
    try:
        if not openai_client or not openai_client.client:
            raise HTTPException(
                status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
                detail="OpenAI服务不可用，请检查配置"
            )
        
        current_time = datetime.now().isoformat()
        
        # 检查是否强制刷新
        if not request.force_refresh:
            cached_result = get_cached_analysis(current_time)
            if cached_result:
                # 返回缓存结果，标记为缓存
                cached_result['cached'] = True
                return AnalysisResponse(**cached_result)
        
        logger.info("生成新的AI分析...")
        
        # 调用AI分析功能
        result = openai_client.get_gold_investment_analysis(
            model=request.model,
            temperature=request.temperature
        )
        
        if "error" in result:
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail=f"AI分析失败: {result['error']}"
            )
        
        # 添加缓存标记
        result['cached'] = False
        result['timestamp'] = current_time
        
        # 保存到缓存
        cache = load_cache()
        cache['last_analysis'] = result.copy()
        cache['last_analysis']['cached_at'] = current_time
        save_cache(cache)
        
        logger.info("AI分析生成成功并已缓存")
        return AnalysisResponse(**result)
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"生成分析时出错: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"分析生成失败: {str(e)}"
        )

@app.delete("/api/admin/reset", summary="重置分析缓存")
async def reset_analysis_cache():
    """重置大模型分析结果缓存"""
    try:
        # 清空缓存文件
        if os.path.exists(CACHE_FILE):
            os.remove(CACHE_FILE)
            logger.info("分析缓存已清除")
            message = "缓存文件已删除"
        else:
            logger.info("缓存文件不存在")
            message = "缓存文件不存在"
        
        return {
            "message": "分析缓存已重置",
            "detail": message,
            "timestamp": datetime.now().isoformat()
        }
        
    except Exception as e:
        logger.error(f"重置缓存时出错: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"重置缓存失败: {str(e)}"
        )

@app.get("/api/admin/cache/status", summary="查看缓存状态")
async def get_cache_status():
    """查看当前缓存状态"""
    try:
        cache = load_cache()
        
        if 'last_analysis' not in cache:
            return {
                "cached": False,
                "message": "无缓存数据",
                "timestamp": datetime.now().isoformat()
            }
        
        last_analysis = cache['last_analysis']
        cache_time = last_analysis.get('cached_at', last_analysis.get('timestamp', ''))
        
        return {
            "cached": True,
            "cache_date": cache_time,
            "is_today": is_same_day(cache_time, datetime.now().isoformat()),
            "model_used": last_analysis.get('model_used', 'unknown'),
            "gold_price": last_analysis.get('gold_price', 0),
            "data_source": last_analysis.get('data_source', 'unknown'),
            "timestamp": datetime.now().isoformat()
        }
        
    except Exception as e:
        logger.error(f"获取缓存状态时出错: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取缓存状态失败: {str(e)}"
        )

@app.get("/api/config/info", summary="查看配置信息")
async def get_config_info():
    """获取当前配置信息（不包含敏感数据）"""
    try:
        global app_config
        if not app_config:
            app_config = load_app_config()
        
        if not app_config:
            return {
                "config_loaded": False,
                "message": "配置文件未加载",
                "config_file": CONFIG_FILE,
                "timestamp": datetime.now().isoformat()
            }
        
        # 返回配置信息，但隐藏敏感数据
        safe_config = {}
        for key, value in app_config.items():
            if 'key' in key.lower() or 'secret' in key.lower():
                # 隐藏敏感信息，只显示前几位和后几位
                if isinstance(value, str) and len(value) > 8:
                    safe_config[key] = f"{value[:4]}...{value[-4:]}"
                else:
                    safe_config[key] = "***"
            else:
                safe_config[key] = value
        
        return {
            "config_loaded": True,
            "config_file": CONFIG_FILE,
            "config": safe_config,
            "timestamp": datetime.now().isoformat()
        }
        
    except Exception as e:
        logger.error(f"获取配置信息时出错: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"获取配置信息失败: {str(e)}"
        )

@app.get("/health", summary="健康检查")
async def health_check():
    """健康检查接口"""
    global app_config
    if not app_config:
        app_config = load_app_config()
    
    # 检查配置状态
    config_status = bool(app_config and app_config.get('openai_api_key'))
    
    return {
        "status": "healthy",
        "timestamp": datetime.now().isoformat(),
        "services": {
            "openai": openai_client is not None and openai_client.client is not None,
            "cache": os.path.exists(CACHE_FILE),
            "config": config_status
        },
        "backend_info": {
            "api_base": app_config.get('openai_base_url', 'unknown') if app_config else 'unknown',
            "config_file": CONFIG_FILE
        }
    }

if __name__ == "__main__":
    # 开发环境运行
    uvicorn.run(
        "app:app",
        host="0.0.0.0",
        port=8000,
        reload=True,
        log_level="info"
    )
